// mpsf.transport.timedisp.js

this.inlets = 1;
this.outlets = 2;
this.autowatch = 1;

sketch.default2d();

	// GIVENS
var num_bars;
var steps_per_bar;
var cur_ticks;
var step_border_width;
var bar_border_width;

var past_step_color;
var cur_step_color;
var after_step_color;
var bar_border_color;
var step_border_color;

	// DERIVED
var w;
var h;

var step_ticks;
var cur_step;
var num_steps;

var step_width;
var bar_width;

var base_drawn;

declareattribute("numbars", "getnumbars", "setnumbars", true);
declareattribute("stepsperbar", "getstepsperbar", "setstepsperbar", true);
declareattribute("curticks", "getcurticks", "setcurticks", true);
declareattribute("stepborderwidth", "getstepborderwidth", "setstepborderwidth", true);
declareattribute("barborderwidth", "getbarborderwidth", "setbarborderwidth", true);
declareattribute("paststepcolor", "getpaststepcolor", "setpaststepcolor", true);
declareattribute("curstepcolor", "getcurstepcolor", "setcurstepcolor", true);
declareattribute("afterstepcolor", "getafterstepcolor", "setafterstepcolor", true);
declareattribute("barbordercolor", "getbarbordercolor", "setbarbordercolor", true);
declareattribute("stepbordercolor", "getstepbordercolor", "setstepbordercolor", true);

initialize();
draw();
refresh();

function dbgdumpall()
{
	dbgdumpgivens();
	dbgdumpcolors();
	dbgdumpderived();
}

function dbgdumpgivens()
{
	outlet(1, "num_bars", num_bars);
	outlet(1, "steps_per_bar", steps_per_bar);
	outlet(1, "cur_ticks", cur_ticks);
	outlet(1, "step_border_width", step_border_width);
	outlet(1, "bar_border_width", bar_border_width);
}

function dbgdumpcolors()
{
	outlet(1, "past_step_color", past_step_color);
	outlet(1, "cur_step_color", cur_step_color);
	outlet(1, "after_step_color", after_step_color);
	outlet(1, "bar_border_color", bar_border_color);
	outlet(1, "step_border_color", step_border_color);
}

function dbgdumpderived()
{
	outlet(1, "w", w);
	outlet(1, "h", h);
	outlet(1, "step_ticks", step_ticks);
	outlet(1, "cur_step", cur_step);
	outlet(1, "num_steps", num_steps);
	outlet(1, "step_width", step_width);
	outlet(1, "bar_width", bar_width);
	outlet(1, "base_drawn", base_drawn);
}

function getnumbars()	{	return num_bars;	}
function getstepsperbar()	{	return steps_per_bar;	}
function getcurticks()	{	return cur_ticks;	}
function getstepborderwidth()	{	return step_border_width;	}
function getbarborderwidth()	{	return bar_border_width;	}
function getpaststepcolor()	{	return past_step_color;	}
function getcurstepcolor()	{	return cur_step_color;	}
function getafterstepcolor()	{	return after_step_color;	}
function getbarbordercolor()	{	return bar_border_color;	}
function getstepbordercolor()	{	return step_border_color;	}

function setstepbordercolor(r, g, b)
{
	if(r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1)
	{
		post("invalid color value");
		return;
	}
	step_border_color[0] = r;
	step_border_color[1] = g;
	step_border_color[2] = b;
	draw();
	refresh();
}

function setbarbordercolor(r, g, b)
{
	if(r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1)
	{
		post("invalid color value");
		return;
	}
	bar_border_color[0] = r;
	bar_border_color[1] = g;
	bar_border_color[2] = b;
	draw();
	refresh();
}

function setafterstepcolor(r, g, b)
{
	if(r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1)
	{
		post("invalid color value");
		return;
	}
	after_step_color[0] = r;
	after_step_color[1] = g;
	after_step_color[2] = b;
	draw();
	refresh();
}

function setcurstepcolor(r, g, b)
{
	if(r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1)
	{
		post("invalid color value");
		return;
	}
	cur_step_color[0] = r;
	cur_step_color[1] = g;
	cur_step_color[2] = b;
	draw();
	refresh();
}

function setpaststepcolor(r, g, b)
{
	if(r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1)
	{
		post("invalid color value");
		return;
	}
	past_step_color[0] = r;
	past_step_color[1] = g;
	past_step_color[2] = b;
	draw();
	refresh();
}

function setbarborderwidth(n)
{
	if(n <= 0)
	{
		post("barborderwidth must be > 0");
		return;
	}
	bar_border_width = n;
	recalc();
	draw();
	refresh();
}

function setstepborderwidth(n)
{
	if(n <= 0)
	{
		post("stepborderwidth must be > 0");
		return;
	}
	step_border_width = n;
	recalc();
	draw();
	refresh();
}

function setcurticks(n)
{
	if(n <= 0)
	{
		post("curticks must be > 0");
		return;
	}
	cur_ticks = n;
	recalc();
	draw();
	refresh();
}

function setnumbars(n)
{
	if(n <= 0)
	{
		post("numbars must be > 0");
		return;
	}
	num_bars = n;
	recalc();
	draw();
	refresh();
}

function setstepsperbar(n)
{
	if(n <= 0)
	{
		post("stepsperbar must be > 0");
		return;
	}
	steps_per_bar = n;
	recalc();
	draw();
	refresh();
}

function dbgpost(str)
{
	//post(str + "\n");
}
dbgpost.local = 1;

function dbgprintrect(r)
{
	//post("[" + r[0] + "] [" + r[1] + "] [" + r[2] + "] [" + r[3] + "]");
}
dbgprintrect.local = 1;

function drawrect(toplft,toprgt,btmrgt,btmlft)
{
	dbgpost("drawrect begin");
	dbgpost("   toplft: " + toplft);
	sketch.quad(toplft[0], toplft[1], 0,
				toprgt[0], toprgt[1], 0,
				btmrgt[0], btmlft[1], 0,
				btmlft[0], btmlft[1], 0);
	dbgpost("drawrect end");
}
drawrect.local = 1;

function getsteprect(n)
{
	dbgpost("getsteprect begin");
	var bar;
	var step;
	var offsetx;
	var i;
	var steprect0 = [[-1, bar_border_width],
					[-1, bar_border_width],
					[-1, h - bar_border_width],
					[-1, h - bar_border_width]];
	var steprect1 = [[], [], [], []];
	if(n >= num_steps)
	{
		dbgpost("getsteprect called for out-of-bounds step");
		return null;
	}
	bar = Math.floor(n / steps_per_bar);
	step = n % steps_per_bar;
	offsetx = (bar_width * bar) + bar_border_width +
				((step_width + step_border_width) * step);
	//post("for step " + n + " bar: " + bar + " step: " + step + " offsetx: " + offsetx + "\n");
	// left
	steprect0[0][0] = steprect0[3][0] = offsetx;
	// right
	steprect0[1][0] = steprect0[2][0] = offsetx + step_width;
	for(i = 0; i < 4; i++)
	{
		steprect1[i] = sketch.screentoworld(steprect0[i][0], steprect0[i][1]);
	}
	dbgpost("getsteprect end");
	dbgpost("   steprect0...");
	dbgprintrect(steprect0);
	dbgpost("\n");
	dbgpost("   steprect1...");
	dbgprintrect(steprect1);
	dbgpost("\n");
	return steprect1;
}

function initialize()
{
	//dbgpost("initialize begin");
	if(past_step_color == null)
	{
		past_step_color		= [0.5, 0.5, 0.5];
	}
	if(bar_border_color == null)
	{
		bar_border_color	= [0.0, 0.0, 0.0];
	}
	if(step_border_color == null)
	{
		step_border_color	= [0.3, 0.3, 0.3];
	}
	if(cur_step_color == null)
	{
		cur_step_color		= [0.7, 0.7, 0.7];
	}
	if(after_step_color == null)
	{
		after_step_color	= [0.9, 0.9, 0.9];
	}
	if(num_bars == null)
	{
		num_bars = 4;
	}
	if(steps_per_bar == null)
	{
		steps_per_bar = 4;
	}
	if(cur_ticks == null)
	{
		cur_ticks = 1440;
	}
	if(bar_border_width == null)
	{
		bar_border_width = 4;
	}
	if(step_border_width == null)
	{
		step_border_width = 2;
	}
	base_drawn = false;
	w = this.box.rect[2] - this.box.rect[0];
	h = this.box.rect[3] - this.box.rect[1];
	recalc();
	//dbgpost("initialize end");
}

function recalc()
{
	dbgpost("recalc begin");
	step_ticks = 1920 / steps_per_bar;
	cur_step = cur_ticks / step_ticks;
	num_steps = steps_per_bar * num_bars;
	step_width = (w - ((num_bars + 1) * bar_border_width) -
					((steps_per_bar - 1) * num_bars * step_border_width)) / num_steps;
	bar_width = bar_border_width + (steps_per_bar * step_width) +
				((steps_per_bar - 1) * step_border_width);
	base_drawn = false;
	dbgpost("recalc end");
}

function draw()
{
	dbgpost("draw begin");
	if(!base_drawn)
	{
		sketch.glclearcolor(1.0, 0.0, 1.0, 1.0);
		sketch.glclear();
		drawbase();
	}
	drawfg();
	dbgpost("draw end");
}

function drawfg()
{
	dbgpost("drawfg begin");
	var step;
	var steprect;
	// draw past steps
	sketch.glcolor(past_step_color[0], past_step_color[1], past_step_color[2]);
	step = 0;
	while(step < cur_step)
	{
		steprect = getsteprect(step);
		drawrect(steprect[0], steprect[1], steprect[2], steprect[3]);
		/*sketch.quad(steprect[0][0], steprect[0][1],
					steprect[1][0], steprect[1][1],
					steprect[2][0], steprect[2][1],
					steprect[3][0], steprect[3][1]);*/
		step++
	}
	// draw cur step
	sketch.glcolor(cur_step_color[0], cur_step_color[1], cur_step_color[2]);
	steprect = getsteprect(cur_step);
	/*sketch.quad(steprect[0][0], steprect[0][1],
				steprect[1][0], steprect[1][1],
				steprect[2][0], steprect[2][1],
				steprect[3][0], steprect[3][1]);*/
	drawrect(steprect[0], steprect[1], steprect[2], steprect[3]);
	// draw after steps
	sketch.glcolor(after_step_color[0], after_step_color[1], after_step_color[2]);
	step = cur_step + 1;
	for(step < num_steps)
	{
		steprect = getsteprect(step);
		/*sketch.quad(steprect[0][0], steprect[0][1],
					steprect[1][0], steprect[1][1],
					steprect[2][0], steprect[2][1],
					steprect[3][0], steprect[3][1]);*/
		drawrect(steprect[0], steprect[1], steprect[2], steprect[3]);
		step++
	}
	dbgpost("drawfg end");
}
drawfg.local = 1;

function drawbase()
{
	dbgpost("drawbase begin");
	var i;
	var j;
	var offsetx;
	var toplft;
	var toprgt;
	var btmrgt;
	var btmlft;
	offsetx = 0;
	// no need to clear since filling the whole area...
	//	draw outer borders
	sketch.glcolor(bar_border_color);
	//		draw top border
	toplft = sketch.screentoworld(0, 0);	// top left
	toprgt = sketch.screentoworld(w, 0);	// top right
	btmrgt = sketch.screentoworld(w, bar_border_width);	// bottom right
	btmlft = sketch.screentoworld(0, bar_border_width);	// bottom left
	/*sketch.quad(toplft[0], toplft[1], toprgt[0], toprgt[1],
				btmrgt[0], btmrgt[1], btmlft[0], btmlft[1]);*/
	drawrect(toplft, toprgt, btmrgt, btmlft);
	//		draw bottom border
	toplft = sketch.screentoworld(0, h - bar_border_width);
	toprgt = sketch.screentoworld(w, h - bar_border_width);
	btmrgt = sketch.screentoworld(w, h);
	btmlft = sketch.screentoworld(0, h);
	/*sketch.quad(toplft[0], toplft[1], toprgt[0], toprgt[1],
				btmrgt[0], btmrgt[1], btmlft[0], btmlft[1]);*/
	drawrect(toplft, toprgt, btmrgt, btmlft);
	//		draw right border
	toplft = sketch.screentoworld(0, 0);
	toprgt = sketch.screentoworld(bar_border_width, 0);
	btmrgt = sketch.screentoworld(bar_border_width, h);
	btmlft = sketch.screentoworld(0, h);
	/*sketch.quad(toplft[0], toplft[1], toprgt[0], toprgt[1],
				btmrgt[0], btmrgt[1], btmlft[0], btmlft[1]);*/
	drawrect(toplft, toprgt, btmrgt, btmlft);
	//		draw left border
	toplft = sketch.screentoworld(w - bar_border_width, 0);
	toprgt = sketch.screentoworld(w, 0);
	btmrgt = sketch.screentoworld(w, h);
	btmlft = sketch.screentoworld(w - bar_border_width, h);
	/*sketch.quad(toplft[0], toplft[1], toprgt[0], toprgt[1],
				btmrgt[0], btmrgt[1], btmlft[0], btmlft[1]);*/
	drawrect(toplft, toprgt, btmrgt, btmlft);
	//	draw bar borders
	//			*note: bar_width is left of one bar border to right of next bar border
	offsetx = 0;
	for(i = 0; i < num_bars - 1; i++)
	{
		offsetx += bar_width;
		toplft = sketch.screentoworld(offsetx, 0);
		toprgt = sketch.screentoworld(offsetx + bar_border_width, 0);
		btmrgt = sketch.screentoworld(offsetx + bar_border_width, h);
		btmlft = sketch.screentoworld(offsetx, h);
		/*sketch.quad(toplft[0], toplft[1], toprgt[0], toprgt[1],
					btmrgt[0], btmrgt[1], btmlft[0], btmlft[1]);*/
		drawrect(toplft, toprgt, btmrgt, btmlft);
	}
	//	draw step borders
	sketch.glcolor(step_border_color[0], step_border_color[1], step_border_color[2]);
	offsetx = 0;
	for(i = 0; i < num_bars; i++)
	{
		offsetx += bar_border_width;
		for(j = 0; j < steps_per_bar - 1; j++)
		{
			offsetx += step_width;
			toplft = sketch.screentoworld(offsetx, bar_border_width);
			toprgt = sketch.screentoworld(offsetx + step_border_width, bar_border_width);
			btmrgt = sketch.screentoworld(offsetx + step_border_width, h - bar_border_width);
			btmlft = sketch.screentoworld(offsetx, h - bar_border_width);
			/*sketch.quad(toplft[0], toplft[1], toprgt[0], toprgt[1],
						btmrgt[0], btmrgt[1], btmlft[0], btmlft[1]);*/
			drawrect(toplft, toprgt, btmrgt, btmlft);
			offsetx += step_border_width;
		}
		//offsetx -= step_border_width;
		offsetx += step_width;
	}
	basedrawn = true;
	dbgpost("drawbase end");
}
drawbase.local = 1;

function onclick(x, y, btn, cmd, shf, cap, opt, ctl)
{
}
onclick.local = 1;

function onresize(w1, h1)
{
	dbgpost("onresize begin");
	w = w1;
	h = h1;
	base_drawn = false;
	draw();
	refresh();
	dbgpost("onresize end");
}
onresize.local = 1;

function msg_int(x)
{
	cur_ticks = x;
	draw();
	refresh();
}


